import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.io.IOException;

public class GameBoard extends JPanel {
    int keyPressed = 0;

    public GameBoard() {
        super();
        setLayout(null);

        setBounds(0, 0, Client.WIDTH, Client.HEIGHT);

        JTextArea saveButton = new JTextArea();
        saveButton.setBounds(10, Client.HEIGHT - 60, 160, 20);
        saveButton.setText("Place your mouse here");
        add(saveButton);

        saveButton.addKeyListener(new KeyListener() {
            @Override
            public void keyTyped(KeyEvent e) {
            }

            @Override
            public void keyPressed(KeyEvent e) {
                char pressed = e.getKeyChar();
                switch (pressed) {
                    case 'w':
                        keyPressed |= Request.MOVE_FORWARD;
                        break;
                    case 'a':
                        keyPressed |= Request.MOVE_LEFT;
                        break;
                    case 's':
                        keyPressed |= Request.MOVE_BACKWARD;
                        break;
                    case 'd':
                        keyPressed |= Request.MOVE_RIGHT;
                        break;
                    case 'j':
                        keyPressed |= Request.TURN_LEFT;
                        break;
                    case 'k':
                        keyPressed |= Request.SHOOT;
                        break;
                    case 'l':
                        keyPressed |= Request.TURN_RIGHT;
                        break;
                    case 'i':
                        keyPressed |= Request.SPEED_UP;
                        break;
                }
                saveButton.setText("");
                Daemon.sendKey(keyPressed);
            }

            @Override
            public void keyReleased(KeyEvent e) {
                char pressed = e.getKeyChar();
                switch (pressed) {
                    case 'w':
                        keyPressed &= ~Request.MOVE_FORWARD;
                        break;
                    case 'a':
                        keyPressed &= ~Request.MOVE_LEFT;
                        break;
                    case 's':
                        keyPressed &= ~Request.MOVE_BACKWARD;
                        break;
                    case 'd':
                        keyPressed &= ~Request.MOVE_RIGHT;
                        break;
                    case 'j':
                        keyPressed &= ~Request.TURN_LEFT;
                        break;
                    case 'k':
                        keyPressed &= ~Request.SHOOT;
                        break;
                    case 'l':
                        keyPressed &= ~Request.TURN_RIGHT;
                        break;
                    case 'i':
                        keyPressed &= ~Request.SPEED_UP;
                        break;
                }
                saveButton.setText("");
                Daemon.sendKey(keyPressed);
            }
        });
    }

    @Override
    public void paint(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        super.paint(g);

        paintField(g);
        paintPlayers(g);
        paintBall(g);
    }

    private Point playerView(float x, float y) {
        Player self = Client.game.getSelf();
        x -= self.x;
        y -= self.y;

        float nx = (float) (x * Math.cos(self.angle) + y * Math.sin(self.angle));
        float ny = (float) (-x * Math.sin(self.angle) + y * Math.cos(self.angle));

        nx += Client.WIDTH / 2;
        ny += Client.HEIGHT / 2;

        return new Point((int) nx, (int) ny);
    }

    private void playerView(float[] srcX, float[] srcY, int[] x, int[] y) {
        int len = srcX.length;
        for (int i = 0; i < len; i++) {
            Point t = playerView(srcX[i], srcY[i]);
            x[i] = t.x;
            y[i] = t.y;
        }
    }

    private Point[] playerView(float[] srcX, float[] srcY) {
        int len = srcX.length;
        Point[] ans = new Point[len];
        for (int i = 0; i < len; i++) {
            ans[i] = playerView(srcX[i], srcY[i]);
        }
        return ans;
    }

    private void paintField(Graphics g) {
        float x = Client.game.field.x;
        float y = Client.game.field.y;
        float[] px = new float[4];
        float[] py = new float[4];
        px[1] = x;
        px[2] = x;
        py[2] = y;
        py[3] = y;
        int[] xs = new int[4];
        int[] ys = new int[4];
        playerView(px, py, xs, ys);
        g.setColor(new Color(0, 116, 56));
        g.fillPolygon(xs, ys, 4);

        g.setColor(new Color(4, 149, 36));
        for (int i = 0; i < 10; i++) {
            py[0] = i * 2 * y / 20;
            py[1] = py[0];
            py[2] = (i * 2 + 1) * y / 20;
            py[3] = py[2];

            playerView(px, py, xs, ys);
            g.fillPolygon(xs, ys, 4);
        }

        g.setColor(new Color(255, 255, 255));
        Graphics2D g2 = (Graphics2D) g;
        g2.setStroke(new BasicStroke(2));
        px[0] = 30;
        py[0] = 50;
        px[1] = x - 30;
        py[1] = 50;
        px[2] = x - 30;
        py[2] = y - 50;
        px[3] = 30;
        py[3] = y - 50;
        playerView(px, py, xs, ys);
        g.drawPolygon(xs, ys, 4);
        px[0] = 30;
        py[0] = Client.game.field.y / 2;
        px[1] = x - 30;
        py[1] = Client.game.field.y / 2;
        playerView(px, py, xs, ys);
        g.drawLine(xs[0], ys[0], xs[1], ys[1]);

        Point point = playerView(Client.game.field.x / 2, Client.game.field.y / 2);
        int radius = 91;
        g.drawOval(point.x - radius, point.y - radius, radius * 2, radius * 2);

        radius = 5;
        g.fillOval(point.x - radius, point.y - radius, radius * 2, radius * 2);
    }

    private void paintPlayers(Graphics g) {
        for (int i = 0; i < Client.game.player_count; ++i) {
            Player player = Client.game.player[i];
            if (player.side == 0) {
                g.setColor(new Color(88, 198, 213));
            } else {
                g.setColor(new Color(215, 215, 215));
            }
            Point point = playerView(player.x, player.y);
            g.fillOval(point.x - (int) player.radius, point.y - (int) player.radius, (int) player.radius * 2, (int) player.radius * 2);
            g.drawString(player.name, point.x - (int) player.radius, point.y - (int) player.radius - 5);

            g.setColor(new Color(77, 80, 81));
            point = playerView(player.x + player.radius/2 * (float) Math.sin(player.angle), player.y - player.radius/2 * (float) Math.cos(player.angle));
            g.fillOval(point.x - (int) player.radius / 2, point.y - (int) player.radius / 2, (int) player.radius, (int) player.radius);
        }
    }

    private void paintBall(Graphics g) {
        try {
            Ball ball = Client.game.ball;
            Image buf = ImageIO.read(new File("src/football.png"));
            Point point = playerView(ball.x, ball.y);
            g.drawImage(buf, point.x - (int) ball.radius,
                    point.y - (int) ball.radius,
                    (int) ball.radius * 2,
                    (int) ball.radius * 2,
                    null);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}
